/* Contabilidade Brasiliense - comportamento do site Compartilhado por todas as paginas. Cada bloco so roda se os elementos que ele usa existirem, porque nem toda pagina tem formulario, FAQ ou hero. */ // menu mobile (function () { var abrir = document.getElementById('open-menu'), fechar = document.getElementById('close-menu'), menu = document.getElementById('mobile-menu'), focoAnterior = null, timerFechar = 0, reduzirMovimento = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (!abrir || !fechar || !menu) return; function itensFocaveis() { return Array.prototype.filter.call( menu.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'), function (item) { return item.offsetParent !== null; } ); } function ocultar() { menu.classList.add('hidden'); menu.classList.remove('flex'); } function set(aberto, devolverFoco) { clearTimeout(timerFechar); if (aberto) focoAnterior = document.activeElement; menu.setAttribute('aria-hidden', !aberto); menu.inert = !aberto; abrir.setAttribute('aria-expanded', aberto); document.body.style.overflow = aberto ? 'hidden' : ''; document.body.classList.toggle('menu-open', aberto); if (aberto) { menu.classList.remove('hidden'); menu.classList.add('flex'); // Separa display e opacidade para a transicao de entrada ser percebida. requestAnimationFrame(function () { menu.classList.add('menu-visible'); fechar.focus(); }); } else if (devolverFoco !== false && focoAnterior && document.contains(focoAnterior)) { focoAnterior.focus(); } if (!aberto) { menu.classList.remove('menu-visible'); if (reduzirMovimento) ocultar(); else timerFechar = setTimeout(ocultar, 210); } } abrir.onclick = function () { set(true); }; fechar.onclick = function () { set(false); }; menu.querySelectorAll('a').forEach(function (a) { a.onclick = function () { set(false, false); }; }); // Submenus acessiveis no celular. Servicos e Segmentos abrem sob demanda, // evitando uma lista longa assim que o menu ocupa a tela. menu.querySelectorAll('[data-mobile-submenu-toggle]').forEach(function (botao) { botao.addEventListener('click', function () { var painel = document.getElementById(botao.getAttribute('aria-controls')), icone = botao.querySelector('.mobile-submenu-icon'), abrirPainel = botao.getAttribute('aria-expanded') !== 'true'; if (!painel) return; botao.setAttribute('aria-expanded', abrirPainel ? 'true' : 'false'); botao.setAttribute('aria-label', (abrirPainel ? 'Fechar' : 'Abrir') + ' submenu'); painel.classList.toggle('hidden', !abrirPainel); if (icone) icone.classList.toggle('rotate-180', abrirPainel); }); }); document.addEventListener('keydown', function (e) { if (!menu.classList.contains('flex')) return; if (e.key === 'Escape') { set(false); return; } if (e.key !== 'Tab') return; var itens = itensFocaveis(), primeiro = itens[0], ultimo = itens[itens.length - 1]; if (!primeiro) return; if (e.shiftKey && document.activeElement === primeiro) { e.preventDefault(); ultimo.focus(); } else if (!e.shiftKey && document.activeElement === ultimo) { e.preventDefault(); primeiro.focus(); } }); window.addEventListener('resize', function () { if (window.innerWidth >= 1024 && menu.classList.contains('flex')) set(false, false); }, { passive: true }); })(); // A barra ganha um pouco mais de definicao depois que sai do topo, sem mudar // de tamanho e sem provocar deslocamento de layout. (function () { var header = document.querySelector('.site-header'); if (!header) return; var agendado = false; function atualizar() { header.classList.toggle('is-scrolled', window.scrollY > 16); agendado = false; } window.addEventListener('scroll', function () { if (agendado) return; agendado = true; requestAnimationFrame(atualizar); }, { passive: true }); atualizar(); })(); // reveal ao rolar + contadores animados (function () { var alvos = document.querySelectorAll('.reveal, .split'); if (!alvos.length) return; var reduzirMovimento = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; function contar(el) { var alvo = +el.dataset.target, sufixo = el.dataset.suffix || ''; if (el.dataset.contado === 'true' || !Number.isFinite(alvo)) return; el.dataset.contado = 'true'; if (reduzirMovimento) { el.textContent = alvo.toLocaleString('pt-BR') + sufixo; return; } var inicio = performance.now(), duracao = 1100; function passo(agora) { var p = Math.min((agora - inicio) / duracao, 1), eased = 1 - Math.pow(1 - p, 3); el.textContent = Math.round(alvo * eased).toLocaleString('pt-BR') + sufixo; if (p < 1) requestAnimationFrame(passo); } requestAnimationFrame(passo); } function exibir(el) { el.classList.remove('reveal-pending'); el.classList.add('in'); el.querySelectorAll('.count').forEach(contar); } if (reduzirMovimento || !('IntersectionObserver' in window)) { alvos.forEach(exibir); return; } var obs = new IntersectionObserver(function (entradas) { entradas.forEach(function (en) { if (!en.isIntersecting) return; exibir(en.target); obs.unobserve(en.target); }); }, { threshold: .12, rootMargin: '0px 0px -5% 0px' }); alvos.forEach(function (el) { var caixa = el.getBoundingClientRect(); if (el.classList.contains('in') || (caixa.top < window.innerHeight * .92 && caixa.bottom > 0)) { exibir(el); return; } el.classList.add('reveal-pending'); obs.observe(el); }); })(); // FAQ (accordion) document.querySelectorAll('.faq-t').forEach(function (botao, indice) { var painelInicial = botao.nextElementSibling; if (!painelInicial) return; if (!botao.id) botao.id = 'faq-botao-' + indice; painelInicial.setAttribute('aria-labelledby', botao.id); painelInicial.setAttribute('aria-hidden', 'true'); painelInicial.inert = true; botao.onclick = function () { var painel = botao.nextElementSibling, icone = botao.querySelector('.faq-i'), aberto = botao.getAttribute('aria-expanded') === 'true'; botao.setAttribute('aria-expanded', !aberto); painel.setAttribute('aria-hidden', aberto ? 'true' : 'false'); painel.inert = aberto; if (icone) { var uso = icone.querySelector('use'); if (uso) { var sprite = (uso.getAttribute('href') || '').split('#')[0]; uso.setAttribute('href', sprite + (aberto ? '#cb-i-lucide-plus' : '#cb-i-lucide-minus')); } } if (aberto) { painel.style.maxHeight = null; } else { painel.style.maxHeight = painel.scrollHeight + 'px'; } }; }); // Mantem a altura de respostas abertas correta quando o texto reflui ao girar // o aparelho ou quando a fonte termina de carregar. (function () { var timer; function ajustarFaqAberto() { document.querySelectorAll('.faq-t[aria-expanded="true"]').forEach(function (botao) { var painel = botao.nextElementSibling; if (painel) painel.style.maxHeight = painel.scrollHeight + 'px'; }); } window.addEventListener('resize', function () { clearTimeout(timer); timer = setTimeout(ajustarFaqAberto, 120); }, { passive: true }); if (document.fonts && document.fonts.ready) document.fonts.ready.then(ajustarFaqAberto); })(); // holofote que segue o mouse document.querySelectorAll('.spot').forEach(function (el) { if ((window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) || (window.matchMedia && window.matchMedia('(hover: none)').matches)) return; var frame = 0, x = 0, y = 0; el.addEventListener('pointermove', function (e) { x = e.clientX; y = e.clientY; if (frame) return; frame = requestAnimationFrame(function () { var r = el.getBoundingClientRect(); el.style.setProperty('--mx', (x - r.left) + 'px'); el.style.setProperty('--my', (y - r.top) + 'px'); frame = 0; }); }, { passive: true }); }); /* --------------------------------------------------------------------------- * MEDICAO * * cbTrack(evento, dados) empurra para o dataLayer e, quando existirem, para o * gtag (GA4 / Google Ads) e o fbq (Meta Pixel). Se nenhuma ferramenta estiver * configurada em partials/head.php, a funcao nao faz nada visivel - e de * proposito, para o site nunca quebrar por causa de tag ausente. * ------------------------------------------------------------------------- */ window.cbTrack = function (evento, dados) { dados = dados || {}; try { (window.dataLayer = window.dataLayer || []).push( Object.assign({ event: evento }, dados) ); if (typeof window.gtag === 'function') window.gtag('event', evento, dados); if (typeof window.fbq === 'function') { // Lead e evento padrao do Meta; o resto vai como evento customizado. if (evento === 'gerar_lead') window.fbq('track', 'Lead', dados); else window.fbq('trackCustom', evento, dados); } } catch (err) { /* medicao nunca pode derrubar a pagina */ } }; // Clique em qualquer CTA marcado com data-cta="..." document.addEventListener('click', function (e) { var alvo = e.target.closest('[data-cta]'); if (!alvo) return; var local = alvo.getAttribute('data-cta'), ehWhats = (alvo.href || '').indexOf('wa.me') > -1; window.cbTrack(ehWhats ? 'clique_whatsapp' : 'clique_cta', { local: local, rotulo: (alvo.textContent || '').trim().slice(0, 60), pagina: document.title }); }); // Estado compartilhado dos formularios: evita cliques duplicados e comunica // para tecnologias assistivas quando uma acao esta em andamento. window.cbAlternarEnvio = function (form, botao, ocupado, rotulo) { if (ocupado && form.dataset.enviando === 'true') return false; form.dataset.enviando = ocupado ? 'true' : 'false'; form.setAttribute('aria-busy', ocupado ? 'true' : 'false'); if (!botao) return true; if (ocupado) { botao.dataset.conteudoOriginal = botao.innerHTML; botao.disabled = true; botao.classList.add('opacity-60'); if (rotulo) botao.textContent = rotulo; } else { botao.disabled = false; botao.classList.remove('opacity-60'); if (botao.dataset.conteudoOriginal) botao.innerHTML = botao.dataset.conteudoOriginal; delete botao.dataset.conteudoOriginal; } return true; }; /* --------------------------------------------------------------------------- * COPIA DO LEAD PARA O N8N * * Chamada por TODOS os formularios do site. A URL vem de window.CB_WEBHOOK, * definida em partials/head.php - nenhum endereco fica escrito aqui. * * O envio nao trava o formulario: nao ha await, nao ha tela de erro e a falha e * engolida de proposito. O caminho principal do lead continua sendo o WhatsApp, * que abre logo em seguida; se o n8n estiver fora do ar, a pessoa nem percebe. * * Detalhes que parecem detalhe e nao sao: * application/json o n8n ja recebe os campos separados, sem precisar de um * passo de parse no fluxo. Custa uma requisicao de * verificacao (preflight) antes do envio, que o webhook * responde 204 liberando POST e content-type; * keepalive mantem o envio de pe mesmo com a aba abrindo o WhatsApp * no instante seguinte. * ------------------------------------------------------------------------- */ window.cbEnviarWebhook = function (formulario, dados) { var url = window.CB_WEBHOOK; if (!url || typeof fetch !== 'function') return; var corpo = { formulario: formulario, pagina: window.location.href, titulo: document.title, enviado_em: new Date().toISOString() }; for (var chave in dados) { if (Object.prototype.hasOwnProperty.call(dados, chave)) corpo[chave] = dados[chave]; } try { fetch(url, { method: 'POST', keepalive: true, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(corpo) })['catch'](function () {}); } catch (e) { /* sem rede, sem fetch: o WhatsApp ja resolve o contato */ } }; /* --------------------------------------------------------------------------- * TELEFONE * * cbTelefone.digitos() reduz o que foi digitado a DDD + numero (11 digitos no * maximo) DESCARTANDO ANTES os prefixos que a pessoa costuma colar junto: * zeros a esquerda (0 de operadora, 00 do internacional) e o 55 do codigo do * pais. Cortar em 11 sem tirar o prefixo era o bug antigo: "+55 61 99926-4714" * virava "(55) 61999-2647" - DDD errado e sem os dois ultimos digitos, ou seja, * lead impossivel de retornar. * * O 55 sai em dois casos: quando sobram mais de 11 digitos com ele, e quando * ha exatamente 11 mas o digito seguinte nao e 9. Celular brasileiro sempre * tem o 9 na frente do numero, entao "55" + algo que nao comeca com 9 nunca e * o DDD 55 - e codigo de pais com o numero ainda incompleto. * * Um celular real de Santa Maria/RS, (55) 9xxxx-xxxx, passa pelos dois testes * intacto: tem 11 digitos e tem o 9 no lugar certo. * ------------------------------------------------------------------------- */ window.cbTelefone = { digitos: function (valor) { // Nenhum DDD comeca com 0, entao zero a esquerda e sempre prefixo. var d = String(valor || '').replace(/\D/g, '').replace(/^0+/, ''); // Comecando com 55, o campo segura 13 digitos em vez de 11: e o espaco do // codigo do pais mais DDD e numero. Sem essa folga nao ha como distinguir // "55 + numero" de "DDD 55" enquanto a pessoa ainda digita. d = d.slice(0, d.slice(0, 2) === '55' ? 13 : 11); // Passou de 11 comecando com 55: o 55 so pode ser codigo de pais. if (d.length > 11 && d.slice(0, 2) === '55') d = d.slice(2); // Empate em 11 digitos: (55) 9xxxx-xxxx e Santa Maria/RS, mas celular // brasileiro SEMPRE tem 9 na frente do numero. Sem esse 9 o que esta ali e // codigo do pais com o numero pela metade - era o caso que a mascara // desenhava como se estivesse completo, e a pessoa enviava assim. if (d.length === 11 && d.slice(0, 2) === '55' && d.charAt(2) !== '9') d = d.slice(2); return d.slice(0, 11); }, mascara: function (valor) { var d = window.cbTelefone.digitos(valor); if (d.length <= 2) return d; if (d.length <= 6) return '(' + d.slice(0, 2) + ') ' + d.slice(2); var corte = d.length > 10 ? 7 : 6; return '(' + d.slice(0, 2) + ') ' + d.slice(2, corte) + '-' + d.slice(corte); } }; /* --------------------------------------------------------------------------- * FORMULARIO DE ANALISE DE CNPJ (landing de regularizacao) * * Destino: o atributo data-endpoint do
. Enquanto o escritorio nao tiver * um endpoint de captacao, o form fica sem esse atributo e o envio abre o * WhatsApp OFICIAL ja com a mensagem montada a partir dos campos. Ou seja: o * lead chega de verdade hoje, sem depender de backend e sem numero escrito no * JS - a URL vem do proprio HTML, renderizado pelo PHP. * ------------------------------------------------------------------------- */ (function () { var form = document.getElementById('form-cnpj'); if (!form) return; var sucesso = document.getElementById('form-cnpj-ok'), falha = document.getElementById('form-cnpj-erro'), botao = form.querySelector('button[type="submit"]'); var digitos = window.cbTelefone.digitos; // mascara de telefone: (61) 99926-4714 var campoZap = form.elements.whatsapp; campoZap.addEventListener('input', function () { campoZap.value = window.cbTelefone.mascara(campoZap.value); }); function erro(campo, mensagem) { var caixa = form.querySelector('[data-erro="' + campo.name + '"]'); campo.setAttribute('aria-invalid', mensagem ? 'true' : 'false'); campo.classList.toggle('campo-invalido', !!mensagem); if (caixa) { caixa.textContent = mensagem || ''; caixa.classList.toggle('hidden', !mensagem); } return !mensagem; } function validar(mostrarTudo) { var c = form.elements, ok = true, primeiro = null; function checa(campo, valido, msg) { var passou = erro(campo, valido ? '' : msg); if (!passou) { ok = false; if (!primeiro) primeiro = campo; } } checa(c.nome, c.nome.value.trim().length >= 2, 'Digite seu nome para sabermos como te chamar.'); checa(c.whatsapp, digitos(c.whatsapp.value).length >= 10, 'Informe um WhatsApp com DDD, para nossa equipe retornar.'); if (!ok && mostrarTudo && primeiro) primeiro.focus(); return ok; } // Revalida enquanto a pessoa corrige, mas so depois da primeira tentativa. var jaTentou = false; form.addEventListener('input', function () { if (jaTentou) validar(false); }); form.addEventListener('change', function () { if (jaTentou) validar(false); }); form.addEventListener('submit', function (e) { e.preventDefault(); jaTentou = true; if (falha) falha.classList.add('hidden'); if (!validar(true)) return; var endpoint = form.getAttribute('data-endpoint'); if (!window.cbAlternarEnvio(form, botao, true, endpoint ? 'Enviando…' : 'Abrindo WhatsApp…')) return; var c = form.elements, dados = { nome: c.nome.value.trim(), whatsapp: c.whatsapp.value.trim() }; window.cbTrack('gerar_lead', { formulario: 'analise-cnpj' }); window.cbEnviarWebhook('analise-cnpj', dados); function concluir() { if (sucesso) { sucesso.classList.remove('hidden'); sucesso.focus(); } form.reset(); jaTentou = false; } if (endpoint) { fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dados) }).then(function (resposta) { if (!resposta.ok) throw new Error('HTTP ' + resposta.status); concluir(); }).catch(function () { if (falha) { falha.classList.remove('hidden'); falha.focus(); } }).then(function () { window.cbAlternarEnvio(form, botao, false); }); return; } // Sem endpoint: leva a conversa para o WhatsApp oficial, ja preenchida. // // A mensagem leva SO o assunto. Repetir "Nome: ... / WhatsApp: ..." nao // informava nada: quem envia esta escrevendo do proprio numero, com o // proprio perfil aberto do outro lado. Os campos continuam sendo coletados // e seguem para o n8n - o que sai e a repeticao dentro da conversa. var base = form.getAttribute('data-whatsapp-base') || ''; if (base) { var texto = 'Olá! Vim pela página de Regularização de CNPJ.'; // aberto de forma sincrona, senao o navegador bloqueia como popup window.open(base + '?text=' + encodeURIComponent(texto), '_blank', 'noopener'); } concluir(); setTimeout(function () { window.cbAlternarEnvio(form, botao, false); }, 900); }); })(); /* --------------------------------------------------------------------------- * FORMULARIO DE MIGRACAO DE CONTABILIDADE * * Usa o WhatsApp oficial recebido do PHP como destino de contingencia. Assim, * nenhum numero de contato fica duplicado neste arquivo e o formulario ja * funciona enquanto nao houver um endpoint de CRM configurado. * ------------------------------------------------------------------------- */ (function () { var form = document.getElementById('form-migracao'); if (!form) return; var sucesso = document.getElementById('form-migracao-ok'), botao = form.querySelector('button[type="submit"]'), campoZap = form.elements.whatsapp, jaTentou = false; var digitos = window.cbTelefone.digitos; campoZap.addEventListener('input', function () { campoZap.value = window.cbTelefone.mascara(campoZap.value); }); function mostrarErro(campo, mensagem) { var caixa = form.querySelector('[data-erro="' + campo.name + '"]'); campo.setAttribute('aria-invalid', mensagem ? 'true' : 'false'); campo.classList.toggle('campo-invalido', !!mensagem); if (caixa) { caixa.textContent = mensagem || ''; caixa.classList.toggle('hidden', !mensagem); } return !mensagem; } function validar(focar) { var c = form.elements, valido = true, primeiro = null; function checar(campo, passou, mensagem) { if (!mostrarErro(campo, passou ? '' : mensagem)) { valido = false; if (!primeiro) primeiro = campo; } } checar(c.nome, c.nome.value.trim().length >= 2, 'Digite seu nome para sabermos como chamar você.'); checar(c.whatsapp, digitos(c.whatsapp.value).length >= 10, 'Informe um WhatsApp com DDD para nossa equipe retornar.'); if (!valido && focar && primeiro) primeiro.focus(); return valido; } form.addEventListener('input', function () { if (jaTentou) validar(false); }); form.addEventListener('change', function () { if (jaTentou) validar(false); }); form.addEventListener('submit', function (e) { e.preventDefault(); jaTentou = true; if (!validar(true)) return; if (!window.cbAlternarEnvio(form, botao, true, 'Abrindo WhatsApp…')) return; var c = form.elements, dados = { nome: c.nome.value.trim(), whatsapp: c.whatsapp.value.trim() }; window.cbTrack('gerar_lead', { formulario: 'migracao-contabilidade' }); window.cbEnviarWebhook('migracao-contabilidade', dados); var base = form.getAttribute('data-whatsapp-base') || ''; if (base) { // so o assunto; ver a explicacao no formulario de analise de CNPJ var texto = 'Olá, vim pela página de Migração de Contabilidade e gostaria de entender como funciona a troca de contador.'; window.cbTrack('clique_whatsapp', { local: 'formulario-migracao', pagina: document.title }); window.open(base + '?text=' + encodeURIComponent(texto), '_blank', 'noopener'); } if (sucesso) { sucesso.classList.remove('hidden'); sucesso.focus(); } form.reset(); jaTentou = false; setTimeout(function () { window.cbAlternarEnvio(form, botao, false); }, 900); }); })(); /* --------------------------------------------------------------------------- * FORMULARIO DE ABERTURA DE CNPJ PARA PROFISSIONAIS DA SAUDE * ------------------------------------------------------------------------- */ (function () { var form = document.getElementById('form-abertura-saude'); if (!form) return; var sucesso = document.getElementById('form-abertura-saude-ok'), botao = form.querySelector('button[type="submit"]'), campoZap = form.elements.whatsapp, jaTentou = false; var digitos = window.cbTelefone.digitos; campoZap.addEventListener('input', function () { campoZap.value = window.cbTelefone.mascara(campoZap.value); }); function mostrarErro(campo, mensagem) { var caixa = form.querySelector('[data-erro="' + campo.name + '"]'); campo.setAttribute('aria-invalid', mensagem ? 'true' : 'false'); campo.classList.toggle('campo-invalido', !!mensagem); if (caixa) { caixa.textContent = mensagem || ''; caixa.classList.toggle('hidden', !mensagem); } return !mensagem; } function validar(focar) { var c = form.elements, valido = true, primeiro = null; function checar(campo, passou, mensagem) { if (!mostrarErro(campo, passou ? '' : mensagem)) { valido = false; if (!primeiro) primeiro = campo; } } checar(c.nome, c.nome.value.trim().length >= 2, 'Digite seu nome para sabermos como chamar você.'); checar(c.whatsapp, digitos(c.whatsapp.value).length >= 10, 'Informe um WhatsApp com DDD para nossa equipe retornar.'); if (!valido && focar && primeiro) primeiro.focus(); return valido; } form.addEventListener('input', function () { if (jaTentou) validar(false); }); form.addEventListener('change', function () { if (jaTentou) validar(false); }); form.addEventListener('submit', function (e) { e.preventDefault(); jaTentou = true; if (!validar(true)) return; if (!window.cbAlternarEnvio(form, botao, true, 'Abrindo WhatsApp…')) return; var c = form.elements, dados = { nome: c.nome.value.trim(), whatsapp: c.whatsapp.value.trim() }; window.cbTrack('gerar_lead', { formulario: 'abertura-cnpj-saude' }); window.cbEnviarWebhook('abertura-cnpj-saude', dados); var base = form.getAttribute('data-whatsapp-base') || ''; if (base) { // so o assunto; ver a explicacao no formulario de analise de CNPJ var texto = 'Olá, vim pela página de Abertura de CNPJ para Profissionais da Saúde e gostaria de entender como abrir minha empresa.'; window.cbTrack('clique_whatsapp', { local: 'formulario-abertura-saude', pagina: document.title }); window.open(base + '?text=' + encodeURIComponent(texto), '_blank', 'noopener'); } if (sucesso) { sucesso.classList.remove('hidden'); sucesso.focus(); } form.reset(); jaTentou = false; setTimeout(function () { window.cbAlternarEnvio(form, botao, false); }, 900); }); })(); /* --------------------------------------------------------------------------- * FORMULARIO DE CONTABILIDADE PARA PROFISSIONAIS DA SAUDE * * Landing consultiva (contabilidade-saude.php), criada depois de a campanha de * abertura de CNPJ ser reprovada pela politica de documentos do Google Ads. O * lead chega ao n8n com o rotulo 'contabilidade-saude' para nao se misturar com * o da landing de abertura. * ------------------------------------------------------------------------- */ (function () { var form = document.getElementById('form-contabilidade-saude'); if (!form) return; var sucesso = document.getElementById('form-contabilidade-saude-ok'), botao = form.querySelector('button[type="submit"]'), campoZap = form.elements.whatsapp, jaTentou = false; var digitos = window.cbTelefone.digitos; campoZap.addEventListener('input', function () { campoZap.value = window.cbTelefone.mascara(campoZap.value); }); function mostrarErro(campo, mensagem) { var caixa = form.querySelector('[data-erro="' + campo.name + '"]'); campo.setAttribute('aria-invalid', mensagem ? 'true' : 'false'); campo.classList.toggle('campo-invalido', !!mensagem); if (caixa) { caixa.textContent = mensagem || ''; caixa.classList.toggle('hidden', !mensagem); } return !mensagem; } function validar(focar) { var c = form.elements, valido = true, primeiro = null; function checar(campo, passou, mensagem) { if (!mostrarErro(campo, passou ? '' : mensagem)) { valido = false; if (!primeiro) primeiro = campo; } } checar(c.nome, c.nome.value.trim().length >= 2, 'Digite seu nome para sabermos como chamar você.'); checar(c.whatsapp, digitos(c.whatsapp.value).length >= 10, 'Informe um WhatsApp com DDD para nossa equipe retornar.'); if (!valido && focar && primeiro) primeiro.focus(); return valido; } form.addEventListener('input', function () { if (jaTentou) validar(false); }); form.addEventListener('change', function () { if (jaTentou) validar(false); }); form.addEventListener('submit', function (e) { e.preventDefault(); jaTentou = true; if (!validar(true)) return; if (!window.cbAlternarEnvio(form, botao, true, 'Abrindo WhatsApp…')) return; var c = form.elements, dados = { nome: c.nome.value.trim(), whatsapp: c.whatsapp.value.trim() }; window.cbTrack('gerar_lead', { formulario: 'contabilidade-saude' }); window.cbEnviarWebhook('contabilidade-saude', dados); var base = form.getAttribute('data-whatsapp-base') || ''; if (base) { // so o assunto; ver a explicacao no formulario de analise de CNPJ var texto = 'Olá, vim pela página de Contabilidade para Profissionais da Saúde e gostaria de falar sobre assessoria contábil.'; window.cbTrack('clique_whatsapp', { local: 'formulario-contabilidade-saude', pagina: document.title }); window.open(base + '?text=' + encodeURIComponent(texto), '_blank', 'noopener'); } if (sucesso) { sucesso.classList.remove('hidden'); sucesso.focus(); } form.reset(); jaTentou = false; setTimeout(function () { window.cbAlternarEnvio(form, botao, false); }, 900); }); })(); /* --------------------------------------------------------------------------- * FORMULARIOS DAS LANDING PAGES POR SEGMENTO * * Um unico comportamento atende as 21 paginas. Segmento, servico e mensagem * saem dos atributos do formulario para o lead chegar identificado no n8n e * no WhatsApp sem manter 21 blocos de JavaScript. * ------------------------------------------------------------------------- */ (function () { var form = document.getElementById('form-segmento-servico'); if (!form) return; var sucesso = document.getElementById('form-segmento-servico-ok'), botao = form.querySelector('button[type="submit"]'), campoZap = form.elements.whatsapp, jaTentou = false; var digitos = window.cbTelefone.digitos; campoZap.addEventListener('input', function () { campoZap.value = window.cbTelefone.mascara(campoZap.value); if (jaTentou) validar(false); }); function mostrarErro(campo, mensagem) { var erro = form.querySelector('[data-erro="' + campo.name + '"]'); campo.setAttribute('aria-invalid', mensagem ? 'true' : 'false'); if (!erro) return; erro.textContent = mensagem || ''; erro.classList.toggle('hidden', !mensagem); } function validar(focar) { var nome = form.elements.nome, erroNome = nome.value.trim().length < 2 ? 'Informe seu nome.' : '', erroZap = digitos(campoZap.value).length < 10 ? 'Informe um WhatsApp válido com DDD.' : ''; mostrarErro(nome, erroNome); mostrarErro(campoZap, erroZap); if (focar && (erroNome || erroZap)) (erroNome ? nome : campoZap).focus(); return !erroNome && !erroZap; } form.elements.nome.addEventListener('input', function () { if (jaTentou) validar(false); }); form.addEventListener('submit', function (evento) { evento.preventDefault(); jaTentou = true; if (!validar(true)) return; if (!window.cbAlternarEnvio(form, botao, true, 'Abrindo WhatsApp…')) return; var segmento = form.getAttribute('data-segmento') || '', servico = form.getAttribute('data-servico') || '', dados = { nome: form.elements.nome.value.trim(), whatsapp: form.elements.whatsapp.value.trim(), segmento: segmento, servico: servico }; window.cbTrack('gerar_lead', { formulario: 'segmento-servico', segmento: segmento, servico: servico }); window.cbEnviarWebhook('segmento-servico', dados); var base = form.getAttribute('data-whatsapp-base') || '', texto = form.getAttribute('data-mensagem') || 'Olá, vim pelo site e gostaria de receber uma orientação.'; if (base) { window.cbTrack('clique_whatsapp', { local: 'formulario-segmentado', segmento: segmento, servico: servico }); window.open(base + '?text=' + encodeURIComponent(texto), '_blank', 'noopener'); } if (sucesso) { sucesso.classList.remove('hidden'); sucesso.focus(); } form.reset(); jaTentou = false; setTimeout(function () { window.cbAlternarEnvio(form, botao, false); }, 900); }); })(); /* O botao flutuante do WhatsApp fica visivel o tempo todo, em todas as paginas. Nao ha JS controlando sua exibicao - e so CSS no partials/footer.php. */